import { apiEndStatus, emptyDefaultImg } from './config'
import { sleep, isObject } from './util'

/**
 * 创建异步加载
 */
export function createLoadData (
  api,
  { 
    id,
    delay = 300
  } = {},
  self
) {
  const _self = self || this
  const stateKey = typeof id === 'string' ? `${id}State` : 'state'

  if (!isObject(_self.data[stateKey])) {
    _self.setData({
      [`${stateKey}`]: {
        isFreshing: false,
        isPending: false,
        isContent: false,
        isError: false,
        error: {}
      }
    })
  }

  async function loadData(freshing = false) {
    if (_self.data[`${stateKey}`].isPending || _self.data[`${stateKey}`].isFreshing) return

    if (!freshing) {
      _self.setData({
        [`${stateKey}.isPending`]: true,
        [`${stateKey}.isContent`]: false,
        [`${stateKey}.isError`]: false,
      })
    } else {
      _self.setData({
        [`${stateKey}.isFreshing`]: true
      })
    }
    
    try {
      const err = await api.call(_self)

      !err && typeof delay === 'number' && delay > 0 && await sleep(delay)

      _self.setData(Object.assign({
        [`${stateKey}.isFreshing`]: false,
        [`${stateKey}.isPending`]: false,
        [`${stateKey}.isContent`]: !err && !freshing,
      }, err && {
        [`${stateKey}.isError`]: true,
        [`${stateKey}.error`]: typeof err === 'string' ? { image: emptyDefaultImg, desc: err } : Object.assign({ image: emptyDefaultImg }, err)
      }))
    } catch (error) {
      const err = apiEndStatus(error)

      _self.setData({
        [`${stateKey}.isFreshing`]: false,
        [`${stateKey}.isPending`]: false,
        [`${stateKey}.isContent`]: false,
        [`${stateKey}.isError`]: true,
        [`${stateKey}.error`]: err
      })
    }
  }

  let _freshing = false
  async function refresh () {
    if (_freshing) return

    _freshing = true
    wx.showNavigationBarLoading()
    await loadData(true)
    wx.hideNavigationBarLoading()
    _freshing = false
  }

  return [
    () => loadData(),
    () => refresh()
  ]
}

/**
 * 创建分页加载
 */
export function createLoadPage (
  api,
  {
    id,
    count = 20
  } = {},
  self
) {
  const _self = self || this
  const _key = typeof id === 'string' ? `${id}Paging` : 'paging'

  function createPaging () {
    return new Promise((resolve, reject) => {
      _self.setData({
        [`${_key}`]: {
          count,
          page: 1,
          isFreshing: false,
          isPending: false,
          isError: false,
          error: {},
          isFirst: true
        }
      }, () => {
        resolve()
      })
    })
  }
  
  let _loading = false
  async function loadPage (freshing = false) {
    const { page, count, isPending, isFreshing, isError } = _self.data[`${_key}`]
    if (_loading || isPending || isFreshing || isError) return

    _loading = true
    _self.setData({
      [`${_key}.isFreshing`]: freshing,
      [`${_key}.isPending`]: !freshing
    })

    try {
      const length = (await api.call(this, page, count)) || 0
      const isFirstErr = page === 1 && length === 0
      const isEnd = length < count

      _self.setData(Object.assign(
        {
          [`${_key}.isPending`]: false,
          [`${_key}.isFirst`]: isFirstErr,
          [`${_key}.isError`]: isEnd,
          [`${_key}.page`]: page + 1,
        },
        freshing && { [`${_key}.isFreshing`]: false },
        isFirstErr && { [`${_key}.error`]: { type: 'empty', desc: '什么都没有哦~', image: emptyDefaultImg } },
        isEnd && { [`${_key}.error`]: { type: 'end', desc: '就这么多啦~', image: emptyDefaultImg } }
      ))
    } catch (error) {
      _self.setData({
        [`${_key}.isPending`]: false,
        [`${_key}.isError`]: true,
        [`${_key}.isFirst`]: page === 1,
        [`${_key}.isFreshing`]: false,
        [`${_key}.error`]: apiEndStatus(error),
      })
    } finally {
      _loading = false
    }
  }

  let _freshing = false
  async function refresh () {
    if (_freshing || _loading) return
    _freshing = true
    wx.showNavigationBarLoading()
    
    await createPaging()
    await loadPage(true)

    wx.hideNavigationBarLoading()
    _freshing = false
  }

  if (!isObject(_self.data[`${_key}`])) {
    createPaging()
  }

  return [
    () => loadPage(),
    () => refresh(),
    () => createPaging()
  ]
}
